/*
	Twit2MSN 1.2.2 
	Created by Matthew Dyson (@WARlrus) - http://www.mattdyson.uni.cc
	
	A basic script to update your MSN Personal Message to your current Twitter Status
	
	Visit http://mattdyson.uni.cc/projects/Twit2MSN/ for help and support
	
	1.2.2 BUG FIXES:
		- Fixed bug from 1.2.1 causing script to fail under certain conditions
	
	1.2.1 BUG FIXES:
		- Fixed bug from 1.2 causing script to not start properly 
	
	NEW IN THIS VERSION:
		- Settings Menu
		- Option to only follow specified hashtags
		- Ignore all hashtags
	
	UPDATED IN THIS VERSION:
		- Better method of file downloading (fixes bug where MSN hangs whilst waiting)
		- Uses new Twitter methods for @replies (appear anywhere in the text)
		- Better way of storing data
	
	KNOWN ISSUES:
		- No handling for private profiles
	
	The following resources have been cited in this script:
		http://www.devx.com/xml/Article/11866/1954
		http://www.w3schools.com/dom/dom_examples.asp
		http://www.astahost.com/info.php/Validate-Numeric_t12732.html
	
	This code has been released under the GPLv3, a copy of which can be found at:
		http://www.gnu.org/licenses/gpl-3.0.txt
*/

var username; // The user's Twitter username
var updateRate; // Update rate in minutes
var ignoreAtReplies; // Should the script ignore @ replies in the profile
var ignoreHashTags;
var onlyTag;
var count=50; // Number between 1 and 200 - the number of tweets to load. Higher number = longer loading time, but more accurate

var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
var Shell=new ActiveXObject("WScript.Shell");
var lastUpdate=0;
var winSettings;
var winAbout;
var regPath;

// Events

//function OnEvent_Signin(Email)
function OnEvent_SigninReady(Email)
{
	OnEvent_Initialize();
}

function OnEvent_Initialize(MessengerStart)
{
	if (Messenger.MyStatus < STATUS_INVISIBLE ) return;
	
	regPath=MsgPlus.ScriptRegPath + Messenger.MyUserId;
	
	if(loadSettings()) {
		startUpdate();	
	}
}

function OnEvent_Timer(TimerId)
{
	Debug.Trace("Timer event received: " + TimerId);
	
	switch(TimerId) {
		default:
			Debug.Trace("Error: Invalid timerID for timer event recieved");
		break;
		
		case "nextUpdate":
			startUpdate();
		break;
	}
}

function OnEvent_DownloadFileComplete(Url, OutFile, Success)
{
	switch(Url) {
		default:
			Debug.Trace("Error downloading file - invalid complete message");
		break;
		
		case "http://twitter.com/statuses/user_timeline/" + username + ".xml?count="+count:
			if(Success) {
				importXML(OutFile);
			} else {
				Debug.Trace("Error downloading file - not successful return")
			}
		break;
	}
}

function OnGetScriptMenu(Location) {

	var ScriptMenu = "<ScriptMenu>";
	
	ScriptMenu+="<MenuEntry Id='settings'>Settings</MenuEntry>";
	ScriptMenu+="<MenuEntry Id='update'>Update Now</MenuEntry>";
	//ScriptMenu+="<Separator/>";
	//ScriptMenu+="<MenuEntry Id='about'>About</MenuEntry>";
	
	ScriptMenu+="</ScriptMenu>";
	
	return ScriptMenu;

}

function OnEvent_MenuClicked(MenuItemId, Location, OriginWnd) {

	switch(MenuItemId) {
		default:
		break;
		
		case "settings":
			openSettingsWindow();
		break;
		
		case "update":
			startUpdate();
		break;
		
		case "about":
		
		break;
	
	} // switch
}

function OnwinSettingsEvent_Cancel(PlusWnd) {

	return !exitSettings(2);
}

function OnwinSettingsEvent_Destroyed(PlusWnd, ExitCode) {
	winSettings=false;
}

function OnwinSettingsEvent_CtrlClicked(PlusWnd, ControlId) {
	switch(ControlId) {
		default:
		
		break;
		
		case "winSettings_buttonCancel":
			exitSettings(2);
		break;
		
		case "winSettings_buttonSave":
			exitSettings(1);
		break;
		
		case "ChkUseTag":
			Interop.Call('user32', 'EnableWindow', winSettings.GetControlHandle('EdtUseTag'), winSettings.Button_IsChecked("ChkUseTag"));
		break;
		
		case "ChkIgnoreHashTags":
			Interop.Call('user32', 'EnableWindow', winSettings.GetControlHandle('ChkUseTag'), !winSettings.Button_IsChecked("ChkIgnoreHashTags"));
		break;
		
	}
}

function OnwinSettingsEvent_EditTextChanged(PlusWnd, ControlId) {
	switch(ControlId) {
		default:
		
		break;
		
		case "EdtUpdateRate":
			checkNumber(winSettings.GetControlText("EdtUpdate"));
		break;
	}
}

// Functions

// calculate the ASCII code of the given character
function CalcKeyCode(aChar) {
  var character = aChar.substring(0,1);
  var code = aChar.charCodeAt(0);
  return code;
}

function checkNumber(val) {
  var strPass = winSettings.GetControlText("EdtUpdateRate");
  var strLength = strPass.length;
  var lchar = winSettings.GetControlText("EdtUpdateRate").charAt((strLength) - 1);
  var cCode = CalcKeyCode(lchar);

  /* Check if the keyed in character is a number
     do you want alphabetic UPPERCASE only ?
     or lower case only just check their respective
     codes and replace the 48 and 57 */

  if (cCode < 48 || cCode > 57 ) {
    var myNumber = winSettings.GetControlText("EdtUpdateRate").substring(0, (strLength) - 1);
    winSettings.SetControlText("EdtUpdateRate", myNumber);
  }
  return false;
}

function exitSettings(ExitCode) {

	if(winSettings.GetControlText("EdtUsername")==false) {
		MsgPlus.DisplayToast("Twit2MSN - Error","You must select a Twitter username");	
		return false;
	}
	
	if(winSettings.GetControlText("EdtUpdateRate")==false || winSettings.GetControlText("EdtUpdateRate")==0) {
		MsgPlus.DisplayToast("Twit2MSN - Error","You must select a valid update rate");	
		return false;
	}
	
	if(ExitCode==1) {
		
		saveSettings();
		loadSettings();
	}
	
	winSettings.close(ExitCode);
	startUpdate();
	return true;
	
}

function loadSettings()
{
	try {
		username = Shell.RegRead(regPath + "\\username");
		updateRate=Shell.RegRead(regPath + "\\updaterate");
		ignoreAtReplies=Shell.RegRead(regPath + "\\ignoreat");
		ignoreHashTags=Shell.RegRead(regPath + "\\ignorehash");
		onlyTag=Shell.RegRead(regPath + "\\onlytag");
		return true;
	} catch(exception) {
		firstRun();
		return false;
	}

}

function saveSettings()
{
	Shell.RegWrite(regPath + "\\username", winSettings.GetControlText("EdtUsername"));
	Shell.RegWrite(regPath + "\\updaterate", winSettings.GetControlText("EdtUpdateRate"));
	Shell.RegWrite(regPath + "\\ignoreat", winSettings.Button_IsChecked("ChkIgnoreReplies"));
	Shell.RegWrite(regPath + "\\ignorehash", winSettings.Button_IsChecked("ChkIgnoreHashTags"));
	
	if(winSettings.Button_IsChecked("ChkUseTag")==true) {
		Shell.RegWrite(regPath + "\\onlytag", winSettings.GetControlText("EdtUseTag"));
	} else {
		Shell.RegWrite(regPath + "\\onlytag", "");
	}
}

function openSettingsWindow()
{
	winSettings = MsgPlus.CreateWnd("winSettings.xml", "winSettings");
	winSettings.SetControlText("EdtUsername", username);
	winSettings.SetControlText("EdtUpdateRate", (updateRate ? updateRate : 5));
	winSettings.Button_SetCheckState("ChkIgnoreReplies", ignoreAtReplies);
	winSettings.Button_SetCheckState("ChkIgnoreHashTags", ignoreHashTags);
	winSettings.SetControlText("EdtUseTag", onlyTag);
	
	if(winSettings.Button_IsChecked("ChkIgnoreHashTags")==false) {
		Interop.Call('user32', 'EnableWindow', winSettings.GetControlHandle('EdtUseTag'), true);
		Interop.Call('user32', 'EnableWindow', winSettings.GetControlHandle('ChkUseTag'), true);
	}
	
	if(onlyTag) {
			winSettings.Button_SetCheckState("ChkUseTag",true);
	} else {
		Interop.Call('user32', 'EnableWindow', winSettings.GetControlHandle('EdtUseTag'), false);
	}
}

function firstRun()
{
	openSettingsWindow();
}

function startUpdate()
{
	if(Messenger.MyStatus!=0)
		{
			MsgPlus.DownloadFile("http://twitter.com/statuses/user_timeline/" + username + ".xml?count="+count);
		}
	MsgPlus.AddTimer("nextUpdate", updateRate*60*1000);
}

function importXML(file)
{
	xmlDoc.async="false";
	xmlDoc.onreadystatechange=verify;
	xmlDoc.load(file);
}

function verify()
{ 
	if(xmlDoc.readyState!=4) return false;
	updateSM();         
}

function updateSM()
{
	x=xmlDoc.getElementsByTagName("text");
	
	var i = 0;
	
	do {
		txt=x[i].childNodes[0].nodeValue;
		i++;
		var skip=false;
		if(txt.indexOf("@")>-1 && ignoreAtReplies==-1) {
			skip=true;
		}
		if(txt.indexOf("#")>-1 && ignoreHashTags==-1) {
			skip=true;
		}
		if(onlyTag && ignoreHashTags==false) {
			skip=true;
			 if(txt.indexOf("#" + onlyTag)>-1) {
			 	skip=false;
			 	txt = txt.replace("#" + onlyTag,"");
			 }
		}
	} while(skip==true && i<x.length);
	
	if(skip==true) {
		txt="";
		var error="No tweets found with the settings you provided.";
		if(onlyTag) {
			error+=" Try removing your hash tag search";
		}
		MsgPlus.DisplayToast("Twit2MSN Error", error);
	}
	
	Messenger.MyPersonalMessage=txt;
	Debug.Trace("Update complete: "+ txt);
}
